import java.util.concurrent.*;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: ws
 * Date: 2023-12-23
 * Time: 21:57
 */
public class T2 {
    public static void main(String[] args) throws InterruptedException {

        // CountDownLatch 倒计时到0，发射（减法）

        // 设定计数
//        CountDownLatch countDownLatch = new CountDownLatch(6);
//
//        for (int i = 1; i <= 6; i++) {
//            new Thread(() -> {
//                System.out.println(Thread.currentThread().getName() + "\t上完自习，离开教室");
//                // 走一个，计数减少一个
//                countDownLatch.countDown();
//            }, String.valueOf(i)).start();
//        }
//
//        // 阻塞当前线程，等待和确定所有人都走完
//        countDownLatch.await();
//
//        System.out.println(Thread.currentThread().getName() + "\t班长最后关门走人");

        /**
         * 班长先跑了
         * main	班长最后关门走人
         * 5	上完自习，离开教室
         * 4	上完自习，离开教室
         * 3	上完自习，离开教室
         *
         * ==================
         *
         * 1	上完自习，离开教室
         * 6	上完自习，离开教室
         * 5	上完自习，离开教室
         * 4	上完自习，离开教室
         * 3	上完自习，离开教室
         * 2	上完自习，离开教室
         * main	班长最后关门走人
         */


        // 七国灭亡，利用 enum 来减少 if 语句的使用
        // 序号后面跟上国家名字
//        CountDownLatch countDownLatch = new CountDownLatch(6);
//
//        for (int i = 1; i <= 6; i++) {
//            new Thread(() -> {
//                System.out.println(Thread.currentThread().getName() + "国，被灭");
//                // 走一个，计数减少一个
//                countDownLatch.countDown();
//            }, CountryEnum.forEachCountryEnum(i).getCode() + CountryEnum.forEachCountryEnum(i).getCountry()).start();
//        }
//
//        countDownLatch.await();
//        System.out.println(Thread.currentThread().getName() + "\t秦，统一");


        // CyclicBarrier 从 0 累加到 指定值，发射（加法）
        // 当减到 0，自动执行 Runnable 方法
//        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
//            System.out.println("已经集齐 7 颗龙珠，召唤神龙");
//        });
//
//        for (int i = 1; i <= 7; i++) {
//            final int tmpInt = i;
//            new Thread(() -> {
//                System.out.println(Thread.currentThread().getName() + "\t收集到第" + tmpInt + "颗龙珠");
//                try {
//                    // 阻塞等待，先拿到龙珠的需要等待，等大家都拿到一起召唤
//                    cyclicBarrier.await();
//                } catch (InterruptedException | BrokenBarrierException e) {
//                    e.printStackTrace();
//                }
//            }, String.valueOf(tmpInt)).start();
//        }


        // Semaphore，信号量
        // 信号量主要用于两个目的，一个是用于多个共享资源的互斥使用，另一个用于并发线程数的控制。
        // 多辆车争抢停车位，先到先得或排队取号
        /**
         * 默认非公平
         *     public Semaphore(int permits) {
         *         sync = new NonfairSync(permits);
         *     }
         * 也可是公平
         *     public Semaphore( int permits, boolean fair){
         *         sync = fair ? new FairSync(permits) : new NonfairSync(permits);
         *      }
         */

        // 资源数固定，不能多
//        Semaphore semaphore = new Semaphore(3);// 3 个车位
//
//        // 模拟 6 辆汽车
//        for (int i = 1; i <= 6; i++) {
//            new Thread(() -> {
//                try {
//                    semaphore.acquire();
//                    System.out.println(Thread.currentThread().getName() + "\t抢到车位");
//                    Thread.sleep(3000);
//                    System.out.println(Thread.currentThread().getName() + "\t停车 3 秒后，离开车位");
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                } finally {
//                    // 释放资源
//                    semaphore.release();
//                }
//            }, String.valueOf(i)).start();
//        }


        // Phaser
        // Phaser是JDK 7新增的一个同步辅助类，
        // 它可以实现CyclicBarrier和CountDownLatch类似的功能，
        // 而且它支持对任务的动态调整，并支持分层结构来达到更高的吞吐量。


        // 模拟了100米赛跑，10名选手，只等裁判一声令下。当所有人都到达终点时，比赛结束。
        // 设置初始的注册人数（1 个裁判）
        final Phaser phaser = new Phaser(1);
        // 十名选手
        for (int index = 0; index < 10; index++) {
            // 每个选手都注册到其中
            phaser.register();
            new Thread(new player(phaser), "player" + index).start();
        }
        System.out.println("Game Start");
        // 裁判下线，注销当前线程,比赛开始
        phaser.arriveAndDeregister();
        // 是否非终止态一直等待，即注册的所有线程都是否已经 arrive
        while (!phaser.isTerminated()) {
        }
        System.out.println("Game Over");

    }


}


class player implements Runnable {

    private final Phaser phaser;

    player(Phaser phaser) {
        this.phaser = phaser;
    }

    @Override
    public void run() {
        try {
            // 第一阶段——等待创建好所有线程再开始
            phaser.arriveAndAwaitAdvance();

            // 第二阶段——等待所有选手准备好再开始
            Thread.sleep((long) (Math.random() * 10000));
            System.out.println(Thread.currentThread().getName() + " ready");
            phaser.arriveAndAwaitAdvance();

            // 第三阶段——等待所有选手准备好到达，到达后，该线程从phaser中注销，不在进行下面的阶段。
            Thread.sleep((long) (Math.random() * 10000));
            System.out.println(Thread.currentThread().getName() + " arrived");
            phaser.arriveAndDeregister();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}



enum CountryEnum {
    ONE(1, "齐"),
    TWO(2, "楚"),
    THREE(3, "燕"),
    FOUR(4, "赵"),
    FIVE(5, "魏"),
    SIX(6, "韩");


    private int code;
    private String country;

    public int getCode() {
        return code;
    }

    public String getCountry() {
        return country;
    }

    CountryEnum(int code, String country) {
        this.code = code;
        this.country = country;
    }

    public static CountryEnum forEachCountryEnum(int index) {
        // 获取当前枚举类的所有
        CountryEnum[] myArray = CountryEnum.values();
        for (CountryEnum element : myArray) {
            if (index == element.getCode()) {
                return element;
            }
        }
        return null;
    }
}